package orm

import (
	"errors"
	"fmt"
	"reflect"
	"strings"
)

func build(meta interface{}, fields, cond, order, limit string, argv ...interface{}) (string, []interface{}) {
	sd := AdaptSetDefiner(meta)
	fp := AdaptFieldInfoProvider(meta)
	fs := fp.Fields()
	r := NewColumnReplacer(meta, fp)
	for _, f := range fs {
		cn, ct, cc := fp.Column(f)
		cond = r.ReplaceCond(f, cond, cn, ct, cc)
		order = r.ReplaceOrder(f, order, cn)
	}
	if fields == "" {
		cs := make([]string, 0)
		for _, f := range fs {
			cn, ct, cc := fp.Column(f)
			cs = append(cs, r.Field(f, cn, ct, cc))
		}
		fields = strings.Join(cs, ", ")
	} else {
		for _, f := range fs {
			cn, ct, cc := fp.Column(f)
			fields = r.ReplaceField(f, fields, cn, ct, cc)
		}
	}
	query := appendCond("SELECT "+fields+" FROM "+ sd.QueryBody(), cond, sd.CondAppendMode())
	if order != "" {
		query += " ORDER BY " + order
	}
	if limit != "" {
		query += " LIMIT " + limit
	}
	return ReplacePlaceHolder(query, argv...)
}

func selectTo(db DataBaseOperator, meta interface{}, data interface{}, cond, order, limit string, argv ...interface{}) error {
	sd := AdaptSetDefiner(meta)
	fp := AdaptFieldInfoProvider(meta)
	fs := fp.Fields()
	if len(fs) == 0 {
		return errors.New("要查询的数据列数为空")
	}
	r := NewColumnReplacer(meta, fp)
	cs := make([]string, 0)
	for _, f := range fs {
		cn, ct, cc := fp.Column(f)
		cs = append(cs, r.Field(f, cn, ct, cc))
		cond = r.ReplaceCond(f, cond, cn, ct, cc)
		order = r.ReplaceOrder(f, order, cn)
	}
	query := appendCond("SELECT "+strings.Join(cs, ", ")+" FROM "+ sd.QueryBody(), cond, sd.CondAppendMode())
	if order != "" {
		query += " ORDER BY " + order
	}
	if limit != "" {
		query += " LIMIT " + limit
	}
	query, argv = ReplacePlaceHolder(query, argv...)
	fmt.Println(query, argv)
	if err := db.Select(data, query, argv...); err != nil {
		return err
	}
	dv := reflect.ValueOf(data).Elem()
	if _, ok := meta.(Agency); ok {
		for i:=0; i< dv.Len(); i++ {
			BindAgent(db, dv.Index(i).Interface().(SimpleTableDefiner))
		}
	}
	return nil
}

func count(db DataBaseOperator, meta interface{}, cond string, argv ...interface{}) (int, error) {
	sd := AdaptSetDefiner(meta)
	fp := AdaptFieldInfoProvider(meta)
	r := NewColumnReplacer(meta, fp)
	for _, f := range fp.Fields() {
		cn, ct, cc := fp.Column(f)
		cond = r.ReplaceCond(f, cond, cn, ct, cc)
	}
	query := appendCond("SELECT count(*) FROM "+ sd.QueryBody(), cond, sd.CondAppendMode())
	count := 0
	query, argv = ReplacePlaceHolder(query, argv...)
	fmt.Println(query, argv)
	if err := db.Get(&count, query, argv...); err != nil {
		return 0, err
	}
	return count, nil
}

func appendCond(query, cond string, mode CondAppendMode) string {
	if cond != "" {
		switch mode {
		case Where:
			return query + " WHERE " + cond
		case Having:
			return query + " HAVING " + cond
		default:
			return query + " AND " + cond
		}
	}
	return query
}
